package de.nak.fireDepartment.service;

import java.util.Collection;
import java.util.LinkedList;

import org.apache.log4j.Logger;
import org.springframework.dao.DataIntegrityViolationException;

import de.nak.fireDepartment.dao.DepartmentDAO;
import de.nak.fireDepartment.exceptions.CarNotFoundException;
import de.nak.fireDepartment.exceptions.DepartmentAlreadyExistsException;
import de.nak.fireDepartment.exceptions.DepartmentNotFoundException;
import de.nak.fireDepartment.exceptions.ErrorOnDeleteException;
import de.nak.fireDepartment.logger.MyLog4JLogger;
import de.nak.fireDepartment.model.Car;
import de.nak.fireDepartment.model.Department;

/**
 * The department service implementation.
 *
 * @author Sven Redelin
 */
public class DepartmentServiceImpl implements DepartmentService {
	
	private Logger logger;
	
	/**
	 * Constructor gets the Logger an creates a message
	 */
	public DepartmentServiceImpl(){
		logger = MyLog4JLogger.getLogger();
		logger.info("Instance of DepartmentServiceImpl has been created");
	}
	
	/**
	 * The department data access object.
	 */
	private DepartmentDAO departmentDAO;
	/**
	 * The car Service
	 */
	private CarService carService;

	/** {@inheritDoc} */
	public void createDepartment(String city,
								 String zipcode,
								 String street,
								 int houseNumber,
								 String telephoneNumber,
								 String telefaxNumber,
								 String homepageURL,
								 String eMail,
								 String descriptionText,
								 String chief,
								 String coChief,
								 int members,
								 String imageURL,
								 Long[] carIds) throws DepartmentAlreadyExistsException, CarNotFoundException {
		
		// Create a new Department-Object
		Department department = new Department();
		logger.info("Create department-Object");
		// Store values in new Department Object
		department.setCity (city);
		department.setZipcode(zipcode);
		department.setStreet(street);
		department.setHouseNumber(houseNumber);
		department.setTelephoneNumber(telephoneNumber);
		department.setTelefaxNumber(telefaxNumber);
		department.setHomepageURL(homepageURL);
		department.seteMail(eMail);
		department.setDescriptionText(descriptionText);
		department.setChief(chief);
		department.setCoChief(coChief);
		department.setMembers(members);
		department.setImageURL(imageURL);
		
		// initiate List for Cars for the Department
		Collection<Car> cars = new LinkedList<Car>();
		
		// loop over the Array of CarIds and add the car to the List
		logger.info("Get selected Cars for the Department");
		if(carIds != null){
			for(int i = 0; i < carIds.length; i++){
				Long carId = carIds[i];
				if(carId != null && carId > 0){
					Car car = carService.showCar(carId);
					cars.add(car);		
				}
			}
		}
		
		// store carlist into the department
		department.setCars(cars);
		
		logger.info("Department has been created");
		try {
			// check for existing Department
			checkDepartmentExists(department);
			// save Department
			departmentDAO.save(department);
			logger.info("Department has been saved");
		}
		catch (DataIntegrityViolationException ex) {
			logger.warn(ex.getStackTrace());
			throw new DepartmentAlreadyExistsException();
		}
		
	}

	/** {@inheritDoc} */
	public Collection<Department> listDepartments() {
		logger.info("List of Departments is requested");
		return departmentDAO.findAll();
	}

	/** {@inheritDoc} */
	public Department showDepartment(Long id) throws DepartmentNotFoundException {
		logger.info("A Department is searched for");
		Department department = departmentDAO.findById(id);
		if (department == null) {
			logger.warn("Department not found");
			throw new DepartmentNotFoundException();
		}
		logger.info("Searched Department found");
		
		// Convert PersistentCarObjects to CarList
		logger.info("get cars of the department");
		Collection<Car> cars = new LinkedList<Car>();
		for (Car car : department.getCars()) {
			cars.add(car);
		}
		department.setCars(cars);
		
		return department;
	}

	/** {@inheritDoc} */
	public void updateDepartment(long id,
								 String city,
								 String zipcode,
								 String street,
								 int houseNumber,
								 String telephoneNumber,
								 String telefaxNumber,
								 String homepageURL,
								 String eMail,
								 String descriptionText,
								 String chief,
								 String coChief,
								 int members,
								 String imageURL,
								 Long[] carIds) throws DepartmentNotFoundException, CarNotFoundException, DepartmentAlreadyExistsException {
		
		logger.info("A Department should be updated");
		Department department = departmentDAO.findById(id);
		if (department == null) {
			logger.warn("Department not found");
			throw new DepartmentNotFoundException();
		}		
		logger.info("Searched Department found");
		
		// check for existing Department
		checkDepartmentExists(department);
		
		department.setCity (city);
		department.setZipcode(zipcode);
		department.setStreet(street);
		department.setHouseNumber(houseNumber);
		department.setTelephoneNumber(telephoneNumber);
		department.setTelefaxNumber(telefaxNumber);
		department.setHomepageURL(homepageURL);
		department.seteMail(eMail);
		department.setDescriptionText(descriptionText);
		department.setChief(coChief);
		department.setCoChief(coChief);
		department.setMembers(members);
		
		// initiate List for Cars for the Department
		Collection<Car> cars = new LinkedList<Car>();
		
		// loop over the array of CarIds and add the cars to the List
		logger.info("Get selected Cars for the Department");
		if(carIds != null){
			for(int i = 0; i < carIds.length; i++){
				Long carId = carIds[i];
				if(carId != null && carId > 0){
					Car car = carService.showCar(carId);
					cars.add(car);		
				}
			}
		}
		department.setCars(cars);

		if(!imageURL.equals("")){
			department.setImageURL(imageURL);
		}
		
		logger.info("Department has been updated");
	}

	/** {@inheritDoc} */
	public void deleteDepartment(Long id) throws DepartmentNotFoundException, ErrorOnDeleteException {
		logger.info("Department should be deleted");
		// get the department
		Department department = departmentDAO.findById(id);
		if (department == null) {
			logger.warn("Department not found");
			throw new DepartmentNotFoundException();
		}
		
		departmentDAO.delete(department);
		logger.info("Department has been deleted");
	}
	
	/**
	 * Check if a Department is alreadyExisting
	 * @param department
	 * @throws DepartmentAlreadyExistsException
	 */
	private void checkDepartmentExists(Department department) throws DepartmentAlreadyExistsException{
		Collection<Department> departments = listDepartments();
		// iterate over all departments
		for (Department dept : departments) {
			// if department equals department (plz and city) and id != id
			if(department.equals(dept) && department.getDeptId() != dept.getDeptId()){
				throw new DepartmentAlreadyExistsException("text.error.departmentExists");
			}
		}
	}

	/**
	 * Returns the department DAO.
	 * @return the departmentDAO.
	 */
	public DepartmentDAO getDepartmentDAO() {
		return departmentDAO;
	}

	/**
	 * Sets the department DAO.
	 * @param departmentDAO the departmentDAO to set.
	 */
	public void setDepartmentDAO(DepartmentDAO departmentDAO) {
		this.departmentDAO = departmentDAO;
	}
	
	/**
	 * Gets the carService
	 * @return carService
	 */
	public CarService getCarService() {
		return carService;
	}

	/**
	 * Sets the carService
	 * @param carService
	 */
	public void setCarService(CarService carService) {
		this.carService = carService;
	}
	
}
